package com.jetinno.utils

import android.annotation.SuppressLint
import android.content.Context
import android.content.SharedPreferences
import java.lang.reflect.Type
import kotlin.reflect.KProperty

/**
 * Created by chenxz on 2018/4/21.
 * kotlin委托属性+SharedPreference实例
 */
/**
 * @param name key名
 * @param default 默认值
 * @param type 解析对象类型时必须值
 */
open class Preference<T>(val name: String, private val default: T, val type: Type? = null) {

    companion object {
//        private lateinit var prefs: SharedPreferences
//        fun init(context: Context) {
//            prefs = context.getSharedPreferences("MilkInterval", Context.MODE_PRIVATE)
//        }

        @JvmStatic
        val prefs: SharedPreferences by lazy {
            ContextHolder.getApplicationContext().getSharedPreferences("MilkInterval", Context.MODE_PRIVATE)
        }

        /**
         * 删除全部数据
         */
        @JvmStatic
        fun clearPreference() {
            prefs.edit().clear().apply()
        }

        /**
         * 根据key删除存储数据
         */
        @JvmStatic
        fun clearPreference(key: String) {
            prefs.edit().remove(key).apply()
        }

        /**
         * 查询某个key是否已经存在
         *
         * @param key
         * @return
         */
        @JvmStatic
        fun contains(key: String): Boolean {
            return prefs.contains(key)
        }

        @JvmStatic
        fun <T> getValue(name: String, default: T): T {
            return getValue(name, default, null)
        }

        @JvmStatic
        fun <T> getValue(name: String, default: T, type: Type? = null): T {
            val t = when (default) {
                is Long -> {
                    prefs.getLong(name, default)
                }
                is String -> {
                    prefs.getString(name, default)
                }
                is Int -> {
                    prefs.getInt(name, default)
                }
                is Boolean -> {
                    prefs.getBoolean(name, default)
                }
                is Float -> {
                    prefs.getFloat(name, default)
                }
                else -> {
                    val defaultJson = JsonUtil.anyToJson(default!!)
                    val json = prefs.getString(name, defaultJson)
                    val obj = JsonUtil.jsonToAny<T>(json, type!!)!!
                    return obj
                }
            }
            return t as T
        }

        @JvmStatic
        fun <T> setValue(name: String, value: T) = with(prefs.edit()) {
            when (value) {
                is Long -> putLong(name, value)
                is String -> putString(name, value)
                is Int -> putInt(name, value)
                is Boolean -> putBoolean(name, value)
                is Float -> putFloat(name, value)
                else -> putString(name, JsonUtil.anyToJson(value!!))
            }.apply()
        }

        /**
         * 返回所有的键值对
         *
         * @param context
         * @return
         */
        @JvmStatic
        fun getAll(): Map<String, *> {
            return prefs.all
        }
    }

    operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return getSharedPreferences(name, default)
    }

    operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        putSharedPreferences(name, value)
    }

    @SuppressLint("CommitPrefEdits")
    private fun putSharedPreferences(name: String, value: T) = with(prefs.edit()) {
        when (value) {
            is Long -> putLong(name, value)
            is String -> putString(name, value)
            is Int -> putInt(name, value)
            is Boolean -> putBoolean(name, value)
            is Float -> putFloat(name, value)
            else -> putString(name, JsonUtil.anyToJson(value!!))
        }.apply()
    }

    @Suppress("UNCHECKED_CAST")
    private fun getSharedPreferences(name: String, default: T): T {
        val t = when (default) {
            is Long -> {
                prefs.getLong(name, default)
            }
            is String -> {
                prefs.getString(name, default)
            }
            is Int -> {
                prefs.getInt(name, default)
            }
            is Boolean -> {
                prefs.getBoolean(name, default)
            }
            is Float -> {
                prefs.getFloat(name, default)
            }
            else -> {
                val defaultJson = JsonUtil.anyToJson(default!!)
                val json = prefs.getString(name, defaultJson)
                val obj = JsonUtil.jsonToAny<T>(json, type!!)!!
                return obj
            }
        }
        return t as T
    }

}
